﻿using PressOB_Framework.ViewModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Timers;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using MessageBox = System.Windows.Forms.MessageBox;

namespace PressOB_Framework
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        MainWindowModel mainWindowModel; // 绑定的model
        System.Timers.Timer timerSend;
        System.Windows.Forms.Timer timerPaint;
        int fpsPaint = 10;
        MyChart[] myChart = new MyChart[4];
        Random random = new Random();
        string nowTime;
        SerialCommunication serialCommunication;
        public MainWindow()
        {
            InitializeComponent();
            mainWindowModel = (MainWindowModel)FindResource("mainWindowModel");
            GetAvailableSerialPorts();
            InitChart();
        }

        private void InitChart()
        {
            if(timerSend == null)
            {
                timerSend = new System.Timers.Timer();
                timerSend.Enabled = false;
                timerSend.Interval = 1000 / int.Parse(mainWindowModel.TimesPs);
                timerSend.Elapsed += TimerSend_Elapsed;
            }
            
            if (timerPaint == null)
            {
                timerPaint = new System.Windows.Forms.Timer();
                timerPaint.Interval = 1000 / fpsPaint;
                timerPaint.Enabled = false;
                timerPaint.Tick += TimerPaint_Elapsed;
            }

            myChart[0] = new MyChart(ChartPlot1,1);
            myChart[1] = new MyChart(ChartPlot2,2);
            myChart[2] = new MyChart(ChartPlot3,3);
            myChart[3] = new MyChart(ChartPlot4,4);

        }

        private void TimerPaint_Elapsed(object sender, EventArgs e)
        {
            //throw new NotImplementedException();
            for (int i = 0; i < myChart.Length; i++)
            {
                myChart[i].RePaint();
                myChart[i].title.Text = "传感器" + (i + 1) + "：" + myChart[i].lastVal.ToString("+#00.000; -#00.000;"); 
            }
        }

        private void TimerSend_Elapsed(object sender, ElapsedEventArgs e)
        {
            if (serialCommunication != null)
            {
                // 挂载函数
                if (!serialCommunication.hasHander)
                {
                    serialCommunication.AddDataReceived(new SerialDataReceivedEventHandler(DataReceivedHandler));
                }
                serialCommunication.SendData(new MyMessage().MsgAll);
            }
        }
        // 收到数据
        private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                // 获取串口对象
                SerialPort sp = (SerialPort)sender;

                // 接收缓冲区
                byte[] ReDatas = new byte[sp.BytesToRead];
                if (ReDatas.Length >= 21)
                {
                    // 读取数据
                    sp.Read(ReDatas, 0, ReDatas.Length);
                    MyMessage msg;
                    msg = new MyMessage(MsgMode.Receive, ReDatas);
                    if (msg.MsgAll == null)
                    {
                        return;
                    }
                    //MyMessage msg = new MyMessage(MsgMode.Receive, ReDatas);
                    string format = DateTime.Now.ToString("【HH:mm:ss.fff】");
                    string[] data = new string[myChart.Length];
                    for (int i = 0; i < myChart.Length; i++)
                    {
                        myChart[i].lastVal = msg.DataF[i];
                        myChart[i].dataY.Dequeue();
                        myChart[i].dataY.Enqueue(myChart[i].lastVal);
                        data[i] = myChart[i].lastVal.ToString("+#00.000; -#00.000;");
                    }
                    string lineData = format + string.Join(", ", data) + "【" + ReDatas.Length.ToString("#0000") + "】\n";
                    // 写入数据
                    File.AppendAllText(mainWindowModel.Path + "\\" + nowTime + ".txt", lineData);
                }
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void run_Click(object sender, RoutedEventArgs e)
        {
            if (!mainWindowModel.IsRun)
            {
                if(mainWindowModel.Path == null || mainWindowModel.Path == "")
                {
                    MessageBox.Show("请选择保存路径");
                    return;
                }
                // 组网
                if (serialCommunication == null)
                {
                    serialCommunication = new SerialCommunication();
                    serialCommunication.StartSerial(mainWindowModel.Com, int.Parse(mainWindowModel.Frequency));
                }
                timerSend.Interval = 1000 / int.Parse(mainWindowModel.TimesPs);
                timerSend.Start();
                timerPaint.Start();
                mainWindowModel.SaveSetting();
                DateTime now = DateTime.Now;
                nowTime = now.ToString("yyyyMMdd_HHmmss");
                File.AppendAllText(mainWindowModel.Path + "\\" + nowTime + ".txt","【数据开始采集日期："+ now.ToString("yyyy年MM月dd日 HH:mm:ss.fff】\n"));
            }
            else
            {
                timerSend.Stop();
                timerPaint.Stop();
                // 终止本次采样
                for (int i = 0; i < myChart.Length; i++)
                {
                    myChart[i].ClearData();
                    myChart[i].RePaint();
                }
            }
            // 可以操作
            mainWindowModel.IsRun = !mainWindowModel.IsRun;
            if (!mainWindowModel.IsRun)
            {
                mainWindowModel.IsPause = false;
            }
        }

        private void save_Click(object sender, RoutedEventArgs e)
        {
            FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
            if (folderBrowserDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string folderPath = folderBrowserDialog.SelectedPath;
                // 在这里使用所选文件夹路径进行操作
                mainWindowModel.Path = folderPath;
            }
        }
        private void pause_Click(object sender, RoutedEventArgs e)
        {
            if (mainWindowModel.IsPause)
            {
                File.AppendAllText(mainWindowModel.Path + "\\" + nowTime + ".txt", "【此处暂停】\n");
                timerSend.Start();
                timerPaint.Start();
            }
            else
            {
                timerSend.Stop();
                timerPaint.Stop();
            }
            // 可以操作
            mainWindowModel.IsPause = !mainWindowModel.IsPause;
        }
        private void GetAvailableSerialPorts()
        {
            mainWindowModel.Ports = SerialPort.GetPortNames();
        }

        private void fresh_Click(object sender, RoutedEventArgs e)
        {
            GetAvailableSerialPorts();
        }
        // crc-16校验
        public static byte[] CalculateCrc(byte[] data)
        {
            ushort crc = 0xFFFF;
            foreach (byte b in data)
            {
                crc ^= b; // 异或当前字节

                for (int i = 0; i < 8; i++)
                {
                    if ((crc & 0x0001) == 1)
                    {
                        crc >>= 1;
                        crc ^= 0xA001; // 异或多项式 0xA001
                    }
                    else
                    {
                        crc >>= 1;
                    }
                }
            }
            byte[] crcBytes = new byte[2];
            crcBytes[0] = (byte)(crc & 0xFF); // 取低八位作为低位字节
            crcBytes[1] = (byte)(crc >> 8);   // 右移八位取高位字节
            return crcBytes;
        }
        // 内部类处理图表
        private class MyChart
        {
            public double[] dataX;
            public Queue<double> dataY;
            public Chart chart;
            private Series series;
            public Title title;
            public double lastVal;
            private int id;

            public int Id { get => id; set => id = value; }

            public MyChart()
            {

            }
            public MyChart(Chart ChartPlot,int id)
            {
                dataX = new double[1000];
                dataY = new Queue<double>();
                chart = ChartPlot;
                Id = id;
                for (int i = 0; i < 1000; i++)
                {
                    dataX[i] = i + 1;
                    dataY.Enqueue(0);
                }
                ChartArea chartArea = new ChartArea("Line");
                series = new Series();
                chartArea.AxisX.Enabled = AxisEnabled.True;
                chartArea.AxisX.Interval = 100;
                chartArea.AxisX.Minimum = 0;
                chartArea.AxisX.Maximum = 1000;
                chartArea.AxisX.Crossing = -20;
                chartArea.AxisY.Enabled = AxisEnabled.True;
                chartArea.AxisY.Interval = 5;
                chartArea.AxisY.Minimum = -20;
                chartArea.AxisY.Maximum = 20;
                series.ChartArea = "Line";
                series.ChartType = SeriesChartType.Line;
                series.Points.DataBindXY(dataX, dataY.ToArray());
                title = chart.Titles.Add("传感器"+ Id +"：+00.000");
                chart.ChartAreas.Add(chartArea);
                chart.Series.Add(series);
            }
            public void RePaint()
            {
                if (chart != null)
                {
                    try
                    {
                        series.Points.DataBindXY(dataX, dataY.ToArray());
                    }catch(Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                }
            }
            public void ClearData()
            {
                if (chart != null)
                {
                    dataY = new Queue<double>();
                    for (int i = 0; i < 1000; i++)
                    {
                        dataY.Enqueue(0);
                    }
                    title.Text = "传感器" + Id + "：+00.000";
                }
            }
        }
        private enum MsgMode
        {
            Send,
            Receive
        }
        private class MyMessage
        {
            private byte[] msgAll,data;
            private MsgMode mode;
            private float[] dataF;

            public byte[] MsgAll { get => msgAll; set => msgAll = value; }
            public byte[] Data { get => data; set => data = value; }
            private MsgMode Mode { get => mode; set => mode = value; }
            public float[] DataF { get => dataF; set => dataF = value; }

            public MyMessage() : this(MsgMode.Send) { }
            public MyMessage(MsgMode mode) {
                Mode = mode;
                if (mode == MsgMode.Send)
                {
                    msgAll = new byte[] { 0x01, 0x03, 0x00, 0x64, 0x00, 0x08, 0x05, 0xD3 };
                }
            }
            public MyMessage(MsgMode mode,byte[] msg)
            {
                Mode = mode;
                if(mode == MsgMode.Receive)
                {
                    if(msg[0] == 0x01 && msg[1]==0x03 && msg[2] == 0x10)
                    {
                        try
                        {
                            msgAll = msg;
                            data = new byte[16];
                            dataF = new float[4];
                            Array.Copy(msg, 3, data, 0, data.Length);
                            Array.Reverse(data);
                            for (int i = 0; i < 4; i++)
                            {
                                dataF[i] = BitConverter.ToSingle(data, (3 - i) * 4);
                                dataF[i] = (float)Math.Floor(dataF[i] * 1000) / 1000;
                                if (float.IsNegativeInfinity(dataF[i]))
                                {
                                    dataF[i] = 0;
                                }
                            }
                        }catch(Exception ex)
                        {
                            MessageBox.Show(ex.Message);
                        }
                    }
                }
            }
        }

        private class SerialCommunication
        {
            static SerialPort serialPort;
            public bool hasHander = false;
            public void StartSerial(string com,int fre)
            {
                try
                {
                    serialPort = new SerialPort(com, fre, Parity.None, 8, StopBits.One);
                    // 打开串口
                    serialPort.Open();
                }
                catch
                {
                    throw new Exception("组网错误");
                }
            }
            public void CloseSerial()
            {
                // 关闭串口
                serialPort.Close();
            }
            public void SendData(byte[] data)
            {
                // 发送数据
                serialPort.Write(data, 0, data.Length);
            }
            // 添加数据接收事件处理程序
            public void AddDataReceived(SerialDataReceivedEventHandler DataReceivedHandler)
            {
                serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
                serialPort.ReceivedBytesThreshold = 1;
                hasHander = true;
            }
        }

    }
}
